/**
 * Zoom | 2017 MIT License
 * 官方文档：http://lkx2217.cn
 * 依赖文件：Lkx
 * 模块化前端管理框架 - UI 模块
 * */

(function(win) {

    "use strict";

    //共同获取方法
    //返回基础的document对象
    //基础的querySelector获取方法
    //创建对象的createElement方法
    var native = {
            doc: function() { return document; },
            queryAll: function(dom) { return native.doc().querySelectorAll(dom); },
            create: function(dom) { return native.doc().createElement(dom); }
        },

        //公共字段
        //记录空字段
        field = {
            empty: /^[ ]*$/
        },

        //共同使用方法
        //包括判断数据类型是否正常
        //删增class操作
        //转换传入的dom对象
        common = {

            //判断所需字段的数据类型是否符合规范
            str: function(text) { return (typeof text === 'string' && !field.empty.test(text)) ? true : false; },
            num: function(parameter) { return typeof parameter === 'number' ? true : false; },
            obj: function(parameter) {
                var hasObj;
                for (var o in parameter) {
                    hasObj = true;
                    break;
                }
                return (typeof parameter === 'object' && hasObj) ? true : false;
            },

            //查找dom对象的class值
            hasClass: function(dom, cls) {
                cls = cls || '';
                if (cls.replace(/\s/g, '').length === 0) {
                    return false;
                }
                return new RegExp(' ' + cls + ' ').test(' ' + dom.className + ' ');
            },

            //增加doc对象的class值
            addClass: function(dom, cls) {
                if (!common.hasClass(dom, cls)) {
                    dom.className = dom.className === '' ? cls : dom.className + ' ' + cls;
                }
            },

            //删除doc对象的class值
            removeClass: function(dom, cls) {
                if (common.hasClass(dom, cls)) {
                    var newClass = ' ' + dom.className.replace(/[\t\r\n]/g, '') + ' ';
                    while (newClass.indexOf(' ' + cls + ' ') >= 0) {
                        newClass = newClass.replace(' ' + cls + ' ', ' ');
                    }
                    dom.className = newClass.replace(/^\s+|\s+$/g, '');
                }
            },

            //判断验证对象
            //此方法主要判断是通过变量传输还是.或#的形式传送对象
            //从而进行转换成框架统一识别对象
            domTurn: function(dom, parameter, that) {

                that.parameter = common.obj(parameter) ? parameter : {};

                if (common.str(dom)) {
                    that.dom = native.queryAll(dom);
                } else if (common.num(dom.length)) {
                    that.dom = dom;
                } else {
                    that.dom = {
                        0: dom,
                        length: '1'
                    };
                }
            }
        };

    //放大镜构造函数
    //创建所有类型标签
    //针对不同type进行不同赋值
    var Skeleton = function(parameter1, parameter2, parameter3) {
        this.type = parameter1;
        this.dom = parameter2;
        this.parameter = parameter3;

        this.definition();
        this.materials();
    };

    Skeleton.prototype = {

        //初始化定义
        //定义创建放大镜所需的数组集
        //支持多图片同时放大
        definition: function() {

            //放大标签
            this.bulk = [];
            this.mask = [];
            this.img = [];

            this.domImg = [];

            //显示与隐藏计时器
            this.timer = [];

            //保存用户初始化时自己创建的偏移量
            this.saveDomLeft = [];
            this.saveDomTop = [];
        },

        //创建所有类型放大镜的标签
        //创建统一的结构
        //根据不同的类型进行创建不同的结构
        materials: function() {
            for (var d = 0; d < this.dom.length; d++) {

                this.domImg[d] = this.dom[d].childNodes[1];

                this.mask[d] = native.create('div');
                this.img[d] = native.create('img');

                if (this.type === 0) {
                    this.bulk[d] = native.create('div');
                }

                this.assemble(d);
            }
        },

        //根据放大镜类型进行标签初始化组装
        //不同风格组装类型不同
        assemble: function(row) {

            switch (this.type) {
                case 0:

                    this.bulk[row].appendChild(this.img[row]);
                    this.dom[row].appendChild(this.mask[row]);
                    this.dom[row].appendChild(this.bulk[row]);

                    break;
                case 1:

                    this.mask[row].appendChild(this.img[row]);
                    this.dom[row].appendChild(this.mask[row]);

                    break;
            }

            this.className(row);
        },

        //增加样式class值
        //根据不同类型增加不同class值
        className: function(row) {

            this.img[row].src = this.domImg[row].src;
            common.addClass(this.dom[row], 'Lkx-Zoom');

            switch (this.type) {
                case 0:

                    common.addClass(this.mask[row], 'Lkx-Zoom-mall-mask');
                    common.addClass(this.bulk[row], 'Lkx-Zoom-mall-bulk');

                    break;
                case 1:

                    common.addClass(this.mask[row], 'Lkx-Zoom-lens-mask');

                    break;
            }

            this.copy(row);
        },

        //对放大镜进行宽高赋值
        //赋值依赖于原dom结构
        //根据原dom对象进行调整
        copy: function(row) {

            switch (this.type) {
                case 0:

                    this.saveDomLeft[row] = this.dom[row].offsetLeft + this.dom[row].clientLeft;
                    this.saveDomTop[row] = this.dom[row].offsetTop + this.dom[row].clientTop;

                    this.mask[row].style.width = this.dom[row].clientWidth / this.parameter.amp + 'px';
                    this.mask[row].style.height = this.dom[row].clientHeight / this.parameter.amp + 'px';
                    this.mask[row].style.background = this.parameter.background;

                    this.bulk[row].style.width = this.dom[row].clientWidth + 'px';
                    this.bulk[row].style.height = this.dom[row].clientHeight + 'px';

                    this.bulk[row].style.border = this.parameter.border;
                    this.bulk[row].style.left = (this.dom[row].offsetWidth + this.dom[row].offsetLeft + this.parameter.left) - this.saveDomLeft[row] + 'px';
                    this.bulk[row].style.top = -this.dom[row].clientTop + 'px';

                    break;
                case 1:

                    this.mask[row].style.width = this.parameter.width + 'px';
                    this.mask[row].style.height = this.parameter.height + 'px';

                    break;
            }

            this.mask[row].style.borderRadius = this.parameter.radius + '%';
            this.img[row].style.width = this.domImg[row].clientWidth * this.parameter.amp + 'px';
            this.img[row].style.height = this.domImg[row].clientHeight * this.parameter.amp + 'px';

            this.event(row);
        },

        //事件绑定
        //放大镜使用皆以事件驱动
        //通过绑定事件来展开放大对象
        event: function(row) {

            var that = this;

            that.domImg[row].addEventListener('mouseover', function() {

                common.addClass(that.mask[row], 'Lkx-Zoom-noTra-show');
                common.removeClass(that.mask[row], 'Lkx-Zoom-noTra-hide');

                if (that.type === 0) {
                    clearTimeout(that.timer[row]);
                    that.bulk[row].style.display = 'block';
                    that.timer[row] = setTimeout(function() {
                        common.addClass(that.bulk[row], 'Lkx-Zoom-show');
                        common.removeClass(that.bulk[row], 'Lkx-Zoom-hide');
                    });
                }

                this.addEventListener('mousemove', move);
                this.addEventListener('mouseout', up);
            });

            function move(event) {

                that.event = event || win.event;

                that.moveY = that.event.offsetY;
                that.moveX = that.event.offsetX;

                //将mask偏移量定位鼠标操作的正中央
                //无论是何种风格，都会将mask至于鼠标中央
                that.moveXMiddle = that.moveY - (that.mask[row].offsetHeight / 2);
                that.moveYMiddle = that.moveX - (that.mask[row].offsetWidth / 2);

                if (that.type === 0) {
                    if (that.moveXMiddle <= 0) {
                        that.moveXMiddle = 0;
                    } else if (that.moveXMiddle >= that.dom[row].offsetHeight - (that.mask[row].offsetHeight + (that.dom[row].clientTop * 2))) {
                        that.moveXMiddle = that.dom[row].offsetHeight - (that.mask[row].offsetHeight + (that.dom[row].clientTop * 2));
                    }

                    if (that.moveYMiddle <= 0) {
                        that.moveYMiddle = 0;
                    } else if (that.moveYMiddle >= that.dom[row].offsetWidth - (that.mask[row].offsetWidth + (that.dom[row].clientLeft * 2))) {
                        that.moveYMiddle = that.dom[row].offsetWidth - (that.mask[row].offsetWidth + (that.dom[row].clientLeft * 2));
                    }
                } else {
                    that.imgMoveXMiddle = that.moveY - (that.mask[row].offsetHeight / (that.parameter.amp * 2));
                    that.imgMoveYMiddle = that.moveX - (that.mask[row].offsetWidth / (that.parameter.amp * 2));
                }

                that.mask[row].style.top = that.moveXMiddle + 'px';
                that.mask[row].style.left = that.moveYMiddle + 'px';

                that.img[row].style.top = -((that.type === 0 ? that.moveXMiddle : that.imgMoveXMiddle) * that.parameter.amp) + 'px';
                that.img[row].style.left = -((that.type === 0 ? that.moveYMiddle : that.imgMoveYMiddle) * that.parameter.amp) + 'px';
            }

            function up() {

                common.addClass(that.mask[row], 'Lkx-Zoom-noTra-hide');
                common.removeClass(that.mask[row], 'Lkx-Zoom-noTra-show');

                if (that.type === 0) {

                    common.addClass(that.bulk[row], 'Lkx-Zoom-hide');
                    common.removeClass(that.bulk[row], 'Lkx-Zoom-show');

                    clearTimeout(that.timer[row]);
                    that.timer[row] = setTimeout(function() {
                        that.bulk[row].style.display = 'none';
                    }, 150);
                }
            }
        }
    };

    //向外暴露的Verify构造函数
    //通过此方法开始创建放大镜
    var Zoom = function() {
        this.name = 'Lkx-Zoom';
    };

    Zoom.fn = Zoom.prototype;

    //商城模式
    //在右侧生成一张放大的图片，通过操作左侧来进行定位显示
    Zoom.fn.mall = function(dom, parameter) {

        common.domTurn(dom, parameter, this);

        return new Skeleton(0, this.dom, {
            amp: common.num(this.parameter.amp) ? this.parameter.amp : 3,
            background: common.str(this.parameter.background) ? this.parameter.background : 'rgba(0, 0, 0, 0.4)',
            radius: common.num(this.parameter.radius) ? this.parameter.radius : 0,
            left: common.num(this.parameter.left) ? this.parameter.left : 10,
            border: common.str(this.parameter.border) ? this.parameter.border : 'none',
        });
    };

    //镜头模式
    //在原有图片上，生成类似镜头的放大圆圈，查看局部部分的放大内容
    Zoom.fn.lens = function(dom, parameter) {

        common.domTurn(dom, parameter, this);

        return new Skeleton(1, this.dom, {
            amp: common.num(this.parameter.amp) ? this.parameter.amp : 3,
            radius: common.num(this.parameter.radius) ? this.parameter.radius : 100,
            width: common.num(this.parameter.width) ? this.parameter.width : 150,
            height: common.num(this.parameter.height) ? this.parameter.height : 150,
        });
    };

    win.Zoom = new Zoom();

})(window);